package com.fadis.data;


import com.fadis.FadisException;
import com.fadis.data.base.StringList;
import com.fadis.utils.FadisUtils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class FList {

    public static int lpush(StringList list, String...items){

        for (String item: items){
            list.addFirst(item);
        }

        return list.size();
    }

    public static int rpush(StringList list, String...items){

        for (String item: items){
            list.add(item);
        }

        return list.size();
    }

    public static String lpop(StringList list){
        if(list == null || list.size() == 0) return null;
        return list.removeFirst();
    }

    public static String rpop(StringList list){
        if(list == null || list.size() == 0) return null;
        return list.removeLast();
    }

    public static int len(StringList list){
        return list == null ? 0 : list.size();
    }

    /**
     * 如果 source 不存在，值 nil 被返回，并且不执行其他动作。
     * 如果 source 和 destination 相同，则列表中的表尾元素被移动到表头，并返回该元素，可以把这种特殊情况视作列表的旋转(rotation)操作
     * @param src
     * @param dest
     * @return
     */
    public static String rpop_lpush(StringList src, StringList dest){
        if(src == null || src.size() == 0) return null;
        String s = src.removeLast();
        dest.addFirst(s);
        return s;
    }

    /**
     * 移除（顺序找或倒序找，根据count的符号），最先发现的两个 item
     * @param list
     * @param count
     * @param item
     * @return 几个元素被remove
     */
    public static int lrem(StringList list, int count, String item){
        if(list == null) return 0;

        int maxRemoveCount = 0;
        if(count == 0) maxRemoveCount = Integer.MAX_VALUE;
        else if(count < 0) maxRemoveCount = -count;
        else maxRemoveCount = count;

        LinkedList<Integer> listWillBeRemoved = new LinkedList<>();
        if(count >= 0){
            int start = 0;
            int end = list.size() - 1;
            for (int i = start; i <= end; i++) {
                if((item == null && list.get(i) == null) || item.equals(list.get(i))){
                    listWillBeRemoved.addLast(i);
                }
                if(listWillBeRemoved.size() == maxRemoveCount) break;
            }
        }else{
            int start = list.size() - 1;
            int end = 0;
            for (int i = start; i >= end; i--) {
                if((item == null && list.get(i) == null) || item.equals(list.get(i))){
                    listWillBeRemoved.addFirst(i);
                }
                if(listWillBeRemoved.size() == maxRemoveCount) break;
            }
        }

        int countRemoved = Math.min(maxRemoveCount, listWillBeRemoved.size());
        for (int i = 0; i < countRemoved; i++) {
            list.remove(listWillBeRemoved.get(i) - i);
        }
        return countRemoved;
    }

    public static String lindex(StringList list, int index){
        if(list == null || list.size() == 0) return null;
        int realIndex = FadisUtils.getNormalIndex(index, list.size());
        if(realIndex < 0 || realIndex >= list.size()) return null;
        return list.get(realIndex);
    }

    public static List<String> lrange(StringList list, int start, int stop){
        if(list == null || list.size() == 0) return null;
        int realStart = FadisUtils.getNormalIndex(start, list.size());
        int realStop = FadisUtils.getNormalIndex(stop, list.size());
        if(realStart > list.size() - 1) return null;
        if(realStop > list.size() - 1) realStop = list.size() - 1;
        List<String> sublist = new ArrayList<>();
        if(realStart > realStop) return sublist;
        if(realStart == realStop){
            sublist.add(list.get(realStart));
            return sublist;
        }
        sublist.addAll(list.subList(realStart, realStop+1));
        return sublist;
    }

    public static String lset(StringList list, int index, String value){
        if(list == null || list.size() == 0){
            throw new FadisException(1, "列表null");
        }
        int realIndex = FadisUtils.getNormalIndex(index, list.size());
        if(realIndex < 0 || realIndex >= list.size()){
            throw new FadisException(1, "IndexOutOfBound: " + realIndex);
        }
        list.set(index, value);
        return "OK";
    }

    /**
     *
     * @param list
     * @param pivot
     * @param value
     * @return 空列表返回0，没找到元素pivot返回-1，成功返回列表长度
     */
    public static int linsertBefore(StringList list, String pivot, String value){
        if(list == null || list.size() == 0) return 0;
        int position = -1;
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).equals(pivot)){
                position = i;
                break;
            }
        }

        if(position == -1) return -1;
        list.add(position, value);
        return list.size();
    }

    public static int linsertAfter(StringList list, String pivot, String value){
        if(list == null || list.size() == 0) return 0;
        int position = -1;
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).equals(pivot)){
                position = i;
                break;
            }
        }

        if(position == -1) return -1;
        list.add(position+1, value);
        return list.size();
    }

    public static String trim(StringList list, int start, int stop){
        if(list == null || list.size() == 0) return "OK";

        int realStart = FadisUtils.getNormalIndex(start, list.size());
        int realStop = FadisUtils.getNormalIndex(stop, list.size());
        int len = list.size();

        if(realStart >= len) {
            list.clear();
        }else if(realStart > realStop) {
            list.clear();
        }else {
            if (realStop >= len) realStop = len - 1;

            List<Integer> listWillBeRemoved = new ArrayList<>();
            for (int i = 0; i < realStart; i++) {
                listWillBeRemoved.add(i);
            }
            for (int i = realStop + 1; i < len; i++) {
                listWillBeRemoved.add(i);
            }
            for (int i = 0; i < listWillBeRemoved.size(); i++) {
                list.remove(listWillBeRemoved.get(i) - i);
            }
        }
        return "OK";
    }
}
